package com.tools.utils;

import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;


/**
 * MD5加密工具类
 */
public class MD5Util {

    // 私有构造函数，防止实例化
    private MD5Util() {
        throw new AssertionError("不能实例化MD5Util类");
    }

    /**
     * 对字符串进行MD5加密，返回32位小写结果
     * @param str 待加密的字符串
     * @return 32位小写MD5加密结果
     */
    public static String encrypt32(String str) {
        return encrypt(str, 32, false);
    }

    /**
     * 对字符串进行MD5加密，返回32位大写结果
     * @param str 待加密的字符串
     * @return 32位大写MD5加密结果
     */
    public static String encrypt32Upper(String str) {
        return encrypt(str, 32, true);
    }

    /**
     * 对字符串进行MD5加密，返回16位小写结果
     * @param str 待加密的字符串
     * @return 16位小写MD5加密结果
     */
    public static String encrypt16(String str) {
        return encrypt(str, 16, false);
    }

    /**
     * 对字符串进行MD5加密，返回16位大写结果
     * @param str 待加密的字符串
     * @return 16位大写MD5加密结果
     */
    public static String encrypt16Upper(String str) {
        return encrypt(str, 16, true);
    }

    /**
     * 对字节数组进行MD5加密，返回32位小写结果
     * @param bytes 待加密的字节数组
     * @return 32位小写MD5加密结果
     */
    public static String encrypt32(byte[] bytes) {
        return encrypt(bytes, 32, false);
    }

    /**
     * MD5加密核心方法
     */
    private static String encrypt(String str, int length, boolean upperCase) {
        if (str == null || str.isEmpty()) {
            return "";
        }
        return encrypt(str.getBytes(StandardCharsets.UTF_8), length, upperCase);
    }

    /**
     * MD5加密核心方法
     */
    private static String encrypt(byte[] bytes, int length, boolean upperCase) {
        try {
            // 获取MD5实例
            MessageDigest md5 = MessageDigest.getInstance("MD5");

            // 计算MD5值
            byte[] md5Bytes = md5.digest(bytes);

            // 转换为十六进制字符串
            StringBuilder sb = new StringBuilder();
            for (byte b : md5Bytes) {
                // 将字节转换为十六进制表示
                String hex = Integer.toHexString(0xFF & b);
                if (hex.length() == 1) {
                    sb.append('0');
                }
                sb.append(hex);
            }

            // 根据需要返回16位或32位结果
            String result = sb.toString();
            if (length == 16) {
                result = result.substring(8, 24); // 16位MD5是32位的中间16位
            }

            // 根据需要返回大写或小写结果
            return upperCase ? result.toUpperCase() : result;

        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("MD5加密失败", e);
        }
    }

    // 测试方法
    public static void main(String[] args) {
        String testStr = "12345678";
        System.out.println("32位小写: " + encrypt32(testStr));
        System.out.println("32位大写: " + encrypt32Upper(testStr));
        System.out.println("16位小写: " + encrypt16(testStr));
        System.out.println("16位大写: " + encrypt16Upper(testStr));

        String encryptedPwd = encrypt32("12345678");
        String inputEncrypted = encrypt32("12345678");
        boolean isMatch = encryptedPwd.equals(inputEncrypted);
        System.out.println("密码是否匹配: " + isMatch);

    }

}
